#include "simulation_menu.hpp"
#include "robots.hpp"

//Bemenet: -
//Kimenet: -
//Tevekenyseg: ha nem szabad a toltorobot, csokkenti a toltendo robot hatralevo toltesi idejet;
//              ha vegez a toltessel, maximumra allitja a szallitorobot toltottsegi szintjet, aktiv allapotura valtoztatja,
//              onmaga elerhetove valik, es felszamolodik a toltesi koltseg
void Charger::Charge()
{
    if( !_available )
    {
        _current->DecrWaiting();
        if( !_current->GetWaiting() )
        {
            _current->SetCurrChargeLevel();
            _current->ChangeState();
            _available = true;
            Menu::NewExpense(_current->GetChargePrice());
        }
    }
}

//Bemenet: szallitorobotra mutato pointer
//Kimenet: -
//Tevekenyseg: a csatlakozast kezdemenyezo robot mutatoja megadja, kit kell a toltorobotnak aktualisan toltenie
void Charger::Connect(DeliveryRobot * p) { _current = p; }


//Bemenet: aru-pointerek listaja, elszallitando arumennyiseg
//Kimenet: -
//Tevekenyseg: szukseges feltetel, hogy legyen meg aru, tovabba, hogy azok mar logikailag a raktarban legyenek;
//              ha az adott mennyiseg nem szallithato el egyszerre, csokkenteni kell a robot kapacitasaval
//                  a robot ezzel veszit a toltottsegebol, sot elkepzelheto hogy a szallitastol lemerul, ekkor inaktiv lesz, es minimum a toltesi idore varakozo allapotban marad;
//              egyebkent az adott arubejegyzes egesze torolheto a listabol
//                  ha kiurul a lista, visszater (return)
//                  ha elfogy a felhalmozott, szinten visszater
//                  kulonben a muvelet rekurziv hivasa kovetkezik a csokkentett ertekkel
void DeliveryRobot::Work(list<Ware*> & ware, int cap)
{
    if( !ware.empty() && ware.front()->GetDay() <= Menu::GetCurrDay() )
    {
        int tmp = ware.front()->GetQuantity();
        if( tmp > cap )
        {
            ware.front()->ChangeQuantity(cap);
            --_curr_charge_level;
            if( !GetCurrChargeLevel() )
            {
                _active = false;
                _waiting = _charge_time;
            }
        }
        else
        {
            delete ware.front();
            ware.pop_front();
            if(ware.empty()) return;
            if(ware.front()->GetDay() > Menu::GetCurrDay())
            {
                --_curr_charge_level;
                if( !GetCurrChargeLevel() )
                {
                    _active = false;
                    _waiting = _charge_time;
                }
                return;
            }
            Work(ware, cap-tmp); //rekurziv hivas
        }
    }
}

//funktor, a toltorobot elerhetosegenek vizsgalatara
struct Free
{
    bool operator()(Charger * p) { return p->IsAvailable(); }
};

//Bemenet: toltorobot-pointerek listaja
//Kimenet: -
//Tevekenyseg: egy szallitorobotnak akkor es csak akkor kell csatlakoznia toltorobothoz, ha a toltesi idobol meg semennyi sem telt el
//              nem garantalt, hogy van szabad toltorobot, pedig csak akkor hajthato vegre a csatlakozas
void DeliveryRobot::TryToConnect(std::list<Charger*> & chargers)
{
    if( _waiting == _charge_time )
    {
        chl::iterator p = find_if(chargers.begin(), chargers.end(), Free());
        if( p != chargers.end() )
        {
            (*p)->Connect(this);
            (*p)->ChangeState();
        }
    }
}
